#ifndef move_h
#define move_h

#if HAVE_CONFIG_H
# include <config.h>
#endif

#include <chess.h>

#include <assert.h>
#include <stdint.h>


/*
 * A move is represented by an unsigned integer:
 * - bits 0-5 destination square
 * - bits 6-11 starting square
 * - bits 12-14 promotion
 * - bit 15 unused
 * - bit 16 enpassant capture
 * - bit 17 castling
 * - bits 18-20 unused
 * - bits 21-32 extra information (e.g. score for move ordering)
 */

typedef uint32_t move_t;

#define MAKE_MOVE(from, to)			\
  (assert((from) >= 0 && (from) < 64),		\
   assert((to) >= 0 && (to) < 64),		\
   ((((move_t)from) << 6) | ((move_t)to)))
#define MOVE_FROM(move) (((move) >> 6) & 63)
#define MOVE_TO(move) ((move) & 63)

#define MOVE_PROMOTION(move) (((move) >> 12) & 7)
#define NO_PROMOTION 0
#define SET_MOVE_PROMOTION(move, p)			\
  (assert(MOVE_PROMOTION(move) == NO_PROMOTION),	\
   ((move) |= ((p & 7) << 12)))

#define MOVE_ENPASSANT(move) ((move) & 0x10000)
#define SET_MOVE_ENPASSANT(move) ((move) |= 0x10000)

#define MOVE_IS_CASTLING(move) ((move) & 0x20000)
#define MOVE_WCASTLE_SHORT (MAKE_MOVE(E1, G1) | 0x20000)
#define MOVE_WCASTLE_LONG (MAKE_MOVE(E1, C1) | 0x20000)
#define MOVE_BCASTLE_SHORT (MAKE_MOVE(E8, G8) | 0x20000)
#define MOVE_BCASTLE_LONG (MAKE_MOVE(E8, C8) | 0x20000)

#define MOVE_SET_EXTRA(move, e) \
  (assert(((move_t)e) < 4096),	\
   ((move) = (((move) & 0xfffff) | (((move_t)e) << 20))))

#define MOVE_GET_EXTRA(move)  ((move) >> 20)
#define MOVE_CLEAR_EXTRA(move) MOVE_SET_EXTRA(move, 0);


#define NULL_MOVE 0


/*
 * Compares two moves.
 *
 * Only from, to squares and promotion piece are considered.  If
 * promotion is not set it is considered equivalent to queen.
 */
int same_move(move_t a, move_t b);


#endif  // move_h
